/**
 * @file compass.c
 *
 */

/*********************
*      INCLUDES
*********************/
#include "lv_watch.h"

#if USE_LV_WATCH_COMPASS != 0

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*********************
*      DEFINES
*********************/
#define WATCH_COMPASS_FOR_TEST 1

/**********************
*      TYPEDEFS
**********************/
lv_task_t * compass_task_p = NULL;

/**********************
*  STATIC PROTOTYPES
**********************/
static lv_obj_t * compass_create(lv_obj_t * activity_obj);
static lv_obj_t * compass_check_create(lv_obj_t * activity_obj);
static void compass_prepare_destory(lv_obj_t * activity_obj);
static void compass_check_prepare_destory(lv_obj_t * activity_obj);
static lv_compass_ext_t * compass_get_ext(void);
static void compass_refresh_cb(lv_anim_t * ptr);
static void compass_start_update(void);
static void compass_task(lv_task_t * param);

/**********************
*  STATIC VARIABLES
**********************/
uint32_t test_count = 0;
/**********************
*      MACROS
**********************/

/**********************
 *   GLOBAL FUNCTIONS
 ***********************/
static lv_obj_t * compass_create(lv_obj_t * activity_obj)
{
    if(activity_obj == NULL) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_COMPASS;
        activity_ext.create = compass_create;
        activity_ext.prepare_destory = compass_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
        if(activity_obj == NULL) {
            return(NULL);
        }
    }

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    if(obj == NULL) {
        return(NULL);
    }
    lv_watch_obj_set_anim_mode(obj, LV_WATCH_ANIM_HOR_RIGHT_HIDE);

    lv_compass_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_compass_ext_t));
    lv_obj_t * compass_cont = lv_cont_create(obj, NULL);
    lv_obj_set_size(compass_cont, lv_obj_get_width(obj) * 4 / 3, lv_obj_get_height(obj) * 4 / 3);
    lv_obj_set_style_local_bg_color(compass_cont,LV_CONT_PART_MAIN,LV_STATE_DEFAULT,LV_COLOR_BLACK);
    lv_obj_set_style_local_bg_opa(compass_cont,LV_CONT_PART_MAIN,LV_STATE_DEFAULT,LV_OPA_COVER);
    lv_obj_set_click(compass_cont, false);
    lv_obj_align(compass_cont, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_obj_t * img = lv_img_create(compass_cont, NULL);
    lv_img_set_src(img, ICON_COMPASS_OUT);
    lv_img_set_zoom(img,LV_IMG_ZOOM_NONE * lv_obj_get_width(obj) / 240);
    lv_obj_align(img, compass_cont, LV_ALIGN_CENTER, 0, 0);
    uint8_t pivot_x = lv_obj_get_width(img) / 2;
    uint8_t pivot_y = lv_obj_get_height(img) / 2;
    lv_img_set_pivot(img, pivot_x, pivot_y);
    ext->img_obj = img;

    lv_obj_t * compass_cont2 = lv_cont_create(img, NULL);
    lv_obj_set_size(compass_cont2, WATCH_COMPASS_W, WATCH_COMPASS_H);
    lv_obj_add_style(compass_cont2, LV_CONT_PART_MAIN, &lv_style_transp_tight);
    lv_obj_set_click(compass_cont2, false);
    lv_obj_align(compass_cont2, img, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t *img2 = lv_img_create(compass_cont2, NULL);
    lv_img_set_src(img2, ICON_COMPASS_INSIDE);
    lv_obj_align(img2, compass_cont2, LV_ALIGN_CENTER, 0, WATCH_COMPASS_H_OFFSET);


    lv_obj_t *label = lv_label_create(compass_cont2, NULL);
    lv_label_set_text(label, "");
    lv_obj_add_style(label,LV_LABEL_PART_MAIN, &lv_watch_font20_yellow);
    lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_width(label,lv_obj_get_width(compass_cont2));
    lv_obj_align(label, compass_cont2, LV_ALIGN_CENTER, 0, WATCH_COMPASS_IMG_H_OFFSET);

    ext->label_obj = label;
    ext->compass_cont2 = compass_cont2;
    compass_start_update();

    return(obj);
}

static lv_obj_t * compass_check_create(lv_obj_t * activity_obj)
{
    if(activity_obj == NULL) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_COMPASS_CHECK;
        activity_ext.create = compass_check_create;
        activity_ext.prepare_destory = compass_check_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
        if(activity_obj == NULL) {
            return(NULL);
        }
    }

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    if(obj == NULL) {
        return(NULL);
    }
    lv_watch_obj_set_anim_mode(obj, LV_WATCH_ANIM_HOR_RIGHT_HIDE);
    lv_obj_t * compass_check_cont = lv_cont_create(obj, NULL);
    lv_obj_set_size(compass_check_cont, lv_obj_get_width(obj), lv_obj_get_height(obj));
    lv_obj_set_style_local_bg_color(compass_check_cont,LV_CONT_PART_MAIN,LV_STATE_DEFAULT,LV_COLOR_BLACK);
    lv_obj_set_style_local_bg_opa(compass_check_cont,LV_CONT_PART_MAIN,LV_STATE_DEFAULT,LV_OPA_COVER);
    lv_obj_set_click(compass_check_cont, false);
    lv_obj_align(compass_check_cont, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_obj_t * img = lv_img_create(compass_check_cont, NULL);
    lv_img_set_src(img, ICON_COMPASS_CHECK);
    lv_img_set_zoom(img,LV_IMG_ZOOM_NONE * lv_obj_get_width(obj) / 320);
    lv_obj_align(img, compass_check_cont, LV_ALIGN_CENTER, 0, 0);
    lv_obj_t *label = lv_label_create(compass_check_cont, NULL);
    lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
    lv_obj_add_style(label,LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_set_width(label,lv_obj_get_width(obj));
    lv_label_set_text_id(label,WATCH_TEXT_ID_COMPASS_CHECK);
    lv_obj_align(label, compass_check_cont, LV_ALIGN_IN_TOP_MID, 0, WATCH_COMPASS_LABEL_H_OFFSET);

    return(obj);
}

void compass_create_event_cb(lv_obj_t * btn, lv_event_t event)
{
    (void)btn;
    uint16_t degree;
    if(LV_EVENT_CLICKED == event) {
        lv_watch_png_cache_all_free();

        if(compass_read_req(&degree))
        {
            lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_COMPASS);
            if(activity_obj != NULL) return;

            lv_obj_t * obj = compass_create(NULL);
            LV_ASSERT_MEM(obj);
        }
        else
        {
            lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_COMPASS_CHECK);
            if(activity_obj != NULL) return;
            compass_task_p = lv_task_create(compass_task, WATCH_CHECK_COMPASS_DEGREE_PERIOD, LV_TASK_PRIO_MID, NULL);
            lv_obj_t * obj = compass_check_create(NULL);
            LV_ASSERT_MEM(obj);
        }
    }
}

/**********************
*   STATIC FUNCTIONS
**********************/
static void compass_prepare_destory(lv_obj_t * activity_obj)
{
    lv_watch_png_cache_all_free();
    if(compass_task_p)
    {
        lv_task_del(compass_task_p);
        compass_task_p = NULL;
        printf("compass_task_p has been deleted in %s\n",__FUNCTION__);
    }
    lv_compass_ext_t * ext = compass_get_ext();
    if(ext->var)
    {
        lv_anim_del(&(ext->var),NULL);
    }
}

static void compass_check_prepare_destory(lv_obj_t * activity_obj)
{
    lv_watch_png_cache_all_free();
    if(compass_task_p)
    {
        lv_task_del(compass_task_p);
        compass_task_p = NULL;
        printf("compass_task_p has been deleted in %s\n",__FUNCTION__);
    }
}

static lv_compass_ext_t * compass_get_ext(void)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_COMPASS);
    if(activity_obj == NULL) return NULL;

    lv_obj_t * watch_obj;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    if(watch_obj == NULL) return NULL;

    if(watch_obj) {
        lv_compass_ext_t * ext = lv_obj_get_ext_attr(watch_obj);
        return ext;
    }
    return NULL;
}

static void compass_refresh_label(uint16_t degree)
{
    char *strtmp;
    char str[60];
    char str2[10];
    uint16_t degree_end = (float)(degree / 10);
    lv_compass_ext_t * ext = compass_get_ext();
    memset(str,0,60);
    memset(str2,0,10);
    if((degree > 3375) || (degree <= 225))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_NORTH);
        sprintf(str,
                "%s",
                strtmp);
    }
    else if((degree > 225) && (degree <= 675))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_NORTHEAST);
        sprintf(str,
                "%s",
                strtmp);
    }
    else if((degree > 675) && (degree <= 1125))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_EAST);
        sprintf(str,
                "%s",
                strtmp);
    }
    else if((degree > 1125) && (degree <= 1575))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_SOUTHEAST);
        sprintf(str,
                "%s",
                strtmp);
    }
    else if((degree > 1575) && (degree <= 2025))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_SOUTH);
        sprintf(str,
                "%s",
                strtmp);
    }
    else if((degree > 2025) && (degree <= 2475))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_SOUTHWEST);
        sprintf(str,
                "%s",
                strtmp);
    }
    else if((degree > 2475) && (degree <= 2925))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_WEST);
        sprintf(str,
                "%s",
                strtmp);
    }
    else if((degree > 2925) && (degree <= 3375))
    {
        strtmp = (char *)lv_lang_get_text(WATCH_TEXT_ID_COMPASS_NORTHWEST);
        sprintf(str,
                "%s",
                strtmp);
    }
    strcat(str,":");
    sprintf(str2,"%d",degree_end);
    strcat(str,str2);
    strcat(str,"°");
    lv_label_set_text(ext->label_obj,str);
    lv_obj_align(ext->label_obj, ext->compass_cont2, LV_ALIGN_CENTER, 0, WATCH_COMPASS_IMG_H_OFFSET);
}

static void compass_refresh_cb(lv_anim_t * ptr)
{
    (void)ptr;
    uint16_t degree;
    if(compass_read_req(&degree))
    {
        lv_compass_ext_t * ext = compass_get_ext();
        if(ext)
        {
            lv_img_set_angle(ext->img_obj, -degree);
            compass_refresh_label(degree);
        }
        else
        {
            printf("ext is NULL in %s\n",__FUNCTION__);
        }
    }
    else
    {
        printf("degree is error in %s\n",__FUNCTION__);
    }
}

static void compass_start_update(void)
{
    lv_anim_t a;
    lv_anim_path_t path;
    lv_compass_ext_t * ext = compass_get_ext();
    ext->var = 1;

    lv_anim_path_init(&path);
    lv_anim_path_set_cb(&path, lv_anim_path_step);
    lv_anim_init(&a);
    lv_anim_set_path(&a, &path);
    lv_anim_set_var(&a, &(ext->var));
    lv_anim_set_time(&a, 0);
    lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
    lv_anim_set_repeat_delay(&a, 1000);
    lv_anim_set_start_cb(&a, compass_refresh_cb);

    compass_refresh_cb(NULL);
    lv_anim_start(&a);
}

static void compass_task(lv_task_t * param)
{
    uint16_t degree;
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_COMPASS_CHECK);
    if(compass_read_req(&degree))
    {
        if(activity_obj != NULL)
        {
            compass_check_prepare_destory(activity_obj);
            lv_obj_del(activity_obj);
            printf("ACT_ID_COMPASS_CHECK has been deleted in %s\n",__FUNCTION__);
        }
        activity_obj = lv_watch_get_activity_obj(ACT_ID_COMPASS);
        if(activity_obj != NULL) return;
        lv_obj_t * obj = compass_create(NULL);
        LV_ASSERT_MEM(obj);
    }
    else
    {
        if(activity_obj == NULL)
        {
            lv_obj_t * obj = compass_check_create(NULL);
            LV_ASSERT_MEM(obj);
            printf("ACT_ID_COMPASS_CHECK has been created in %s\n",__FUNCTION__);
        }
    }
}

#if WATCH_COMPASS_FOR_TEST == 1
bool compass_read_req(uint16_t *degree) /* true: degree is valid,false: degree is invalid */
{
    if(test_count <= 10)
    {
        *degree = 0;
        test_count++;
        return false;
    }
    else if((test_count > 10)&&(test_count <= 30))
    {
        *degree = (test_count - 9) * 100;
        test_count++;
        return true;
    }
    else
    {
        *degree = 0;
        test_count = 0;
        return true;
    }
}
#else
bool compass_read_req(uint16_t *degree) /* true: degree is valid,false: degree is invalid */
{
    test_count++;
    test_count = 0;
    return true;
}
#endif
#endif
